home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / xinetd / misc.1.2.2 / ftwx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-08  |  3.7 KB  |  185 lines

  1. /*
  2.  * (c) Copyright 1992 by Panagiotis Tsirigotis
  3.  * All rights reserved.  The file named COPYRIGHT specifies the terms 
  4.  * and conditions for redistribution.
  5.  */
  6.  
  7. static char RCSid[] = "$Id: ftwx.c,v 2.1 1992/10/01 00:41:02 panos Exp $" ;
  8.  
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <sys/file.h>
  12. #ifndef OLD_DIR
  13. #include <dirent.h>
  14. #else
  15. #include <sys/dir.h>
  16. #define dirent direct
  17. #endif
  18.  
  19. extern int errno ;
  20.  
  21. #include "misc.h"
  22. #include "ftwx.h"
  23.  
  24. #define PRIVATE            static
  25.  
  26. #define NUL                    '\0'
  27.  
  28.  
  29. typedef enum { NO, YES } boolean_e ;
  30.  
  31. static struct
  32. {
  33.     int (*stat_func)() ;
  34.     int (*user_func)() ;
  35. } ftwx_data ;
  36.  
  37. /*
  38.  * ftwx is an extension to ftw, that optionally follows symlinks (the
  39.  * default is NOT to follow them).
  40.  *
  41.  * Possible flag values:
  42.  *        FTWX_FOLLOW:         follow symlinks
  43.  *
  44.  * Possible depth values:
  45.  *        0            : means only the specified path
  46.  *        positive : means go as deep as specified
  47.  *        FTWX_ALL : no depth limitation
  48.  *
  49.  * User function return value:
  50.  *        negative : means an error occured and the traversal should stop
  51.  *        0            : OK
  52.  *        positive : means that if the current object is a directory it
  53.  *                      should not be traversed.
  54.  *
  55.  * Return value:
  56.  *        -1         : if an error occurs
  57.  *  frv            : frv is the function return value if it is negative (it
  58.  *                      should not be -1).
  59.  *        0            : if successful
  60.  */
  61. int ftwx( path, func, depth, flags )
  62.     char *path ;
  63.     int (*func)() ;
  64.     int depth ;
  65.     int flags ;
  66. {
  67.     int stat(), lstat() ;
  68.  
  69.     /*
  70.      * Initialize the data structure
  71.      */
  72.     ftwx_data.stat_func = ( flags & FTWX_FOLLOW ) ? stat : lstat ;
  73.     ftwx_data.user_func = func ;
  74.  
  75.     return( ftwx_traverse( path, depth ) ) ;
  76. }
  77.  
  78.  
  79.  
  80.  
  81. /*
  82.  * ftwx_traverse works in two phases:
  83.  *
  84.  * Phase 1: process the current path
  85.  *
  86.  * Phase 2: if the current path is a directory, it invokes ftwx_traverse
  87.  *                for each directory entry
  88.  */
  89. PRIVATE int ftwx_traverse( path, depth )
  90.     char *path ;
  91.     int depth ;
  92. {
  93.     DIR *dirp ;
  94.     struct stat st ;
  95.     int ftw_flag = 0 ;
  96.     boolean_e traverse = YES ;
  97.     int retval ;
  98.     int save_errno ;
  99.  
  100.     if ( (*ftwx_data.stat_func)( path, &st ) == -1 )
  101.         ftw_flag = FTW_NS ;
  102.     else
  103.     {
  104.         /*
  105.          * If it is a directory and determine if it is readable
  106.          * (if it is not readable, we don't traverse it
  107.          */
  108.         if ( S_ISDIR( st.st_mode ) )
  109.             if ( access( path, R_OK ) == 0 )
  110.                 ftw_flag = FTW_D ;
  111.             else
  112.                 ftw_flag = FTW_DNR ;
  113.         else
  114.             ftw_flag = FTW_F ;
  115.     }
  116.     retval = (*ftwx_data.user_func)( path, &st, ftw_flag ) ;
  117.     if ( retval < 0 )
  118.         return( retval ) ;
  119.     else if ( retval > 0 && ftw_flag == FTW_D )
  120.         traverse = NO ;
  121.  
  122.     /*
  123.      * Stop traversal if:
  124.      *        a. depth reached 0
  125.      *        b. the current path is not a readable directory
  126.      *        c. the user doesn't want us to traverse this directory tree
  127.      */
  128.     if ( depth == 0 || ftw_flag != FTW_D || traverse == NO )
  129.         return( 0 ) ;
  130.  
  131.     if ( depth != FTWX_ALL )
  132.         depth-- ;
  133.  
  134.     if ( ( dirp = opendir( path ) ) == NULL )
  135.         return( -1 ) ;
  136.  
  137.     for ( ;; )
  138.     {
  139.         struct dirent *dp ;
  140.         char *filename ;
  141.  
  142.         errno = 0 ;            /* to detect readdir errors */
  143.         dp = readdir( dirp ) ;
  144.         if ( dp == NULL )
  145.         {
  146.             retval = ( errno == 0 ) ? 0 : -1 ;
  147.             break ;
  148.         }
  149.  
  150.         /*
  151.          * The special names: "." and ".." are skipped
  152.          */
  153.         if ( dp->d_name[ 0 ] == '.' )
  154.             if ( dp->d_name[ 1 ] == NUL ||
  155.                         dp->d_name[ 1 ] == '.' && dp->d_name[ 2 ] == NUL )
  156.                 continue ;
  157.  
  158.         filename = make_pathname( 2, path, dp->d_name ) ;
  159.         if ( filename == NULL )
  160.         {
  161.             retval = -1 ;
  162.             break ;
  163.         }
  164.         
  165.         retval = ftwx_traverse( filename, depth ) ;
  166.         free( filename ) ;
  167.  
  168.         /*
  169.          * Check for a negative value instead of -1 because the
  170.          * user function may use any negative value
  171.          */
  172.         if ( retval < 0 )
  173.             break ;
  174.     }
  175.     /*
  176.      * Make sure we don't trash errno; we should only do this if
  177.      * retval is negative, but we are lazy...
  178.      */
  179.     save_errno = errno ;
  180.     (void) closedir( dirp ) ;
  181.     errno = save_errno ;
  182.     return( retval ) ;
  183. }
  184.  
  185.